package com.develop.data.loan.manager.api;

import com.develop.data.loan.model.LoanContract;
import com.develop.data.loan.model.LoanInstallment;
import org.javatuples.Pair;

import javax.money.MonetaryAmount;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public interface LoanRepaymentManager {

    LoanInstallment previewInstallmently(LoanInstallment installment, LocalDateTime point);

    MonetaryAmount previewAmountInstallmently(LoanInstallment installment, LocalDateTime point);


    List<LoanInstallment> preview(LoanContract contract, LocalDateTime point);

    MonetaryAmount previewAmount(LoanContract contract, LocalDateTime point);

    default MonetaryAmount execute(LoanContract contract, LocalDateTime point, MonetaryAmount amount) {

        List<String> amountNames = new ArrayList<>();
        //在一期内，利息和逾期利息，本金和逾期本金不可能同时存在
        //逾期利息和罚息会同时存在，从利出发，先收利，再收利的来源，反向则是先收利的来源再收利，因为人性，所以总是采取前者
        //这个Demo，收益+保本，以下，在一期内，前三种金额和后两种金额不可能同时出现
        Collections.addAll(
                amountNames,
                "installmentPrincipalOverdue",
                "installmentInterestOverdue",
                "installmentInterestPenalty",
                "installmentInterestAccrual",
                "installmentPrincipalDueAccrual"
        );

        List<Integer> terms = contract.getLoanInstallments().stream().filter(installment -> !installment.cleared).map(installment -> installment.installmentTerm).sorted(Collections.reverseOrder()).collect(Collectors.toList());

        List<Pair<Integer, String>> order = terms.stream().flatMap(term -> amountNames.stream().map(amountName -> new Pair<Integer, String>(term, amountName))).collect(Collectors.toList());

        return execute(contract, point, amount, order);

    };

    MonetaryAmount execute(LoanContract contract, LocalDateTime point, MonetaryAmount amount, List<Pair<Integer, String>> order);

}
